import { useState, useEffect } from 'react'

export const INTERACTION_TYPE = {
  MOUSE: 'mouse',
  PEN: 'pen',
  TOUCH: 'touch',
}

const UPDATE_INTERVAL = 1000 // Throttle updates to the type to prevent flip flopping

const useInteraction = (): boolean => {
  const [isTouch, setIsTouch] = useState(false)

  useEffect(() => {
    const hasTapEvent = 'ontouchstart' in window
    setIsTouch(hasTapEvent)

    let localTouch = hasTapEvent
    let lastTouchUpdate = Date.now()

    const shouldUpdate = (): boolean =>
      lastTouchUpdate + UPDATE_INTERVAL < Date.now()

    const onMouseMove = (): void => {
      if (localTouch && shouldUpdate()) {
        setTimeout(() => {
          if (shouldUpdate()) {
            setIsTouch(false)
            localTouch = false
          }
        }, UPDATE_INTERVAL)
      }
    }

    const onTouchStart = (): void => {
      lastTouchUpdate = Date.now()

      if (!localTouch) {
        setIsTouch(true)
        localTouch = true
      }
    }

    const onPointerMove = (e: PointerEvent): void => {
      const { pointerType } = e

      switch (pointerType) {
        case INTERACTION_TYPE.TOUCH:
        case INTERACTION_TYPE.PEN:
          return onTouchStart()
        default:
          return onMouseMove()
      }
    }

    if (hasTapEvent) {
      window.addEventListener('mousemove', onMouseMove)
      window.addEventListener('touchstart', onTouchStart)
    } else {
      window.addEventListener('pointerdown', onPointerMove)
      window.addEventListener('pointermove', onPointerMove)
    }

    return () => {
      if (hasTapEvent) {
        window.removeEventListener('mousemove', onMouseMove)
        window.removeEventListener('touchstart', onTouchStart)
      } else {
        window.removeEventListener('pointerdown', onPointerMove)
        window.removeEventListener('pointermove', onPointerMove)
      }
    }
  }, [])

  return isTouch
}

export default useInteraction
